/***************************************************************************************
* File name    :	ALGRsa_PR.c
* Function     :	
* Author       : 
* Date         :
* Version      : 
* Description  :    
* ModifyRecord :
*****************************************************************************************/
#include <Utils/Type.h>
#include "ALGRsa_PR.h"
#include <mbedtls/rsa.h>
#include <mbedtls/bignum.h>
#include <mbedtls/entropy.h>
#include <mbedtls/ctr_drbg.h>

#include <string.h>

mbedtls_rsa_context rsa_ctx;

static mbedtls_entropy_context entropy;
static mbedtls_ctr_drbg_context ctr_drbg;

/* RSA prototype key. */

UINT32 ReserverIntData(UINT32 Value)
{
	return ((Value & 0xff000000) >> 24) + ((Value & 0x00ff0000) >> 8) + ((Value & 0x0000ff00) << 8) + ((Value & 0xff) << 24);
}

UINT8  ALGRsa_PR_Rsa_Init(void)
{
	const char *pers = "rsa_genkey";
	mbedtls_entropy_init( &entropy );
	mbedtls_ctr_drbg_init( &ctr_drbg );

	mbedtls_rsa_init(&rsa_ctx, MBEDTLS_RSA_PKCS_V15, 0);

	if( ( 0 != mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
		(const unsigned char *) pers,
		strlen( pers ) ) ) )
	{
		return RT_FAIL;
	}
	return RT_OK;
}

/*******************************************************************************
函数原型：	UINT8 ALGRsa_PR_GenKeyPair(R_RSA_PROTO_KEY protoKey, 
								R_RSA_PRIVATE_KEY *pRSAKey)
函数说明：	产生RSA密钥对。
参数说明：	protoKey [I] --- 产生时的参数；
							当产生1024位密钥对时，protoKey->bits=1024；
							当产生2048位密钥对时，protoKey->bits=2048
			protoKey ->PublicExponent一般为3或65537，此值会存放到对应的RSA密钥对结构中的publicExponent中，pRSAKey中publicExponent的存放格式为，publicExponent[0]为最高字节。 
			pRSAKey [O] --- 产生的密钥对。
注意事项:   pRSAKey结构所指向的指针类型数组，地址都必须四字节对齐，如果是全局变量，建议在数组前加个对齐标记__align (4),比如:
			__align UINT8 e[4];
			pRSAKey->publicExponent=e;               
			当签名用CRT方式时，pRSAKey-> exponent可以设置为空NULL
返回值：   RT_OK或RT_FAIL	   
********************************************************************************/
UINT8 ALGRsa_PR_GenKeyPair(R_RSA_PROTO_KEY protoKey,R_RSA_PRIVATE_KEY *pRSAKey)
{	
	if(0 != mbedtls_rsa_gen_key(&rsa_ctx, mbedtls_ctr_drbg_random, &ctr_drbg, protoKey.bits, protoKey.PublicExponent))
	{
		return RT_FAIL;
	}
	pRSAKey->bits = protoKey.bits;
	mbedtls_mpi_write_binary(&rsa_ctx.D, (UINT8*)pRSAKey->exponent, protoKey.bits/8);
	mbedtls_mpi_write_binary(&rsa_ctx.E, (UINT8*)pRSAKey->publicExponent, 4);
	//*pRSAKey->publicExponent = ReserverIntData(*pRSAKey->publicExponent);
	mbedtls_mpi_write_binary(&rsa_ctx.N, (UINT8*)pRSAKey->modulus, protoKey.bits/8);
	mbedtls_mpi_write_binary(&rsa_ctx.P, (UINT8*)pRSAKey->prime[0], protoKey.bits/16);
	mbedtls_mpi_write_binary(&rsa_ctx.Q, (UINT8*)pRSAKey->prime[1], protoKey.bits/16);
	mbedtls_mpi_write_binary(&rsa_ctx.DP, (UINT8*)pRSAKey->primeExponent[0], protoKey.bits/16);
	mbedtls_mpi_write_binary(&rsa_ctx.DQ, (UINT8*)pRSAKey->primeExponent[1], protoKey.bits/16);
	mbedtls_mpi_write_binary(&rsa_ctx.QP, (UINT8*)pRSAKey->coefficient, protoKey.bits/16);

	return RT_OK;
}

/*******************************************************************************
函数原型：	UINT8 ALGRsa_PR_PubKeyOpt(UINT8 *output, UINT32 *outputLen, UINT8 *input, 
								UINT32 inputLen, R_RSA_PUBLIC_KEY *RSAKey)
函数说明：	公钥操作,此函数没有对数据进行Padding，需要自己Padding。此操作可以对数据进行公钥加密或者对私钥加密的数据进行解密。函数用到了R_RSA_PUBLIC_KEY中的exponent和modulus或者R_RSA_PRIVATE_KEY中的publicExponent和modulus两个数组。
参数说明：	output [O] --- 输出结果；
			outputLen [O] --- 输出结果长度，为protoKey->bits/8字节；
			input [I] --- 输入数据；
			InputLen [I] --- 输入数据长度，必须为protoKey->bits/8字节；
			RSAKey [I] --- 公钥，实际上只用到了R_RSA_PRIVATE_KEY中的publicExponent和modulus两个数组，其他可以为空
返回值：	RT_OK或RT_FAIL 
********************************************************************************/
UINT8 ALGRsa_PR_PubKeyOpt(UINT8 *output,UINT32 *outputLen, UINT8 *input,UINT32 inputLen,R_RSA_PUBLIC_KEY *RSAKey)
{

	*RSAKey->publicExponent = ReserverIntData(*RSAKey->publicExponent);
	mbedtls_mpi_read_binary(&rsa_ctx.E, (UINT8*)RSAKey->publicExponent, 4);
	mbedtls_mpi_read_binary(&rsa_ctx.N, (UINT8*)RSAKey->modulus, RSAKey->bits/8);
	rsa_ctx.len = RSAKey->bits/8;

	if(0 != mbedtls_rsa_public(&rsa_ctx, input, output))
	{
		return RT_FAIL;
	}
	return RT_OK;
}

/*******************************************************************************
函数原型：	UINT8 ALGRsa_PR_PriKeyOpt(UINT8 *output, UINT32 *outputLen, UINT8 *input, 
								UINT32 inputLen, R_RSA_PRIVATE_KEY *RSAKey)
函数说明：	私钥操作，此函数没有对数据进行Padding，需要自己Padding。此操作可以对数据进行私钥加密，或者对公钥加密的数据进行解密。私钥中使用了结构体R_RSA_PRIVATE_KEY中的prime[0]、prime[1]、modulus、primeExponent[0]、primeExponent[1]和coefficient。
参数说明：	output [O] --- 输出结果；
			outputLen [O] --- 输出结果长度，为protoKey->bits/8字节；
			input [I] --- 输入数据；
			inputLen [I] --- 输入数据长度，必须为protoKey->bits/8字节；
			RSAKey [I] --- 私钥，私钥中使用了结构体中的prime[0]、prime[1]、modulus、primeExponent[0]、primeExponent[1]和coefficient?
返回值：	RT_OK或RT_FAIL 
********************************************************************************/
UINT8 ALGRsa_PR_PriKeyOpt(UINT8 *output,UINT32 *outputLen, UINT8 *input,UINT32 inputLen,R_RSA_PRIVATE_KEY *RSAKey)
{
	rsa_ctx.len = RSAKey->bits/8;
	mbedtls_mpi_read_binary(&rsa_ctx.D, (UINT8*)RSAKey->exponent, RSAKey->bits/8);
	//mbedtls_mpi_read_binary(&rsa_ctx.E, (UINT8*)RSAKey->publicExponent, 4);
	mbedtls_mpi_read_binary(&rsa_ctx.N, (UINT8*)RSAKey->modulus, RSAKey->bits/8);
	mbedtls_mpi_read_binary(&rsa_ctx.P, (UINT8*)RSAKey->prime[0], RSAKey->bits/16);
	mbedtls_mpi_read_binary(&rsa_ctx.Q, (UINT8*)RSAKey->prime[1], RSAKey->bits/16);
	mbedtls_mpi_read_binary(&rsa_ctx.DP, (UINT8*)RSAKey->primeExponent[0], RSAKey->bits/16);
	mbedtls_mpi_read_binary(&rsa_ctx.DQ, (UINT8*)RSAKey->primeExponent[1], RSAKey->bits/16);
	mbedtls_mpi_read_binary(&rsa_ctx.QP, (UINT8*)RSAKey->coefficient, RSAKey->bits/16);
	
	if(0 != mbedtls_rsa_private(&rsa_ctx, NULL, NULL, input, output))
	{
		return RT_FAIL;
	}

	return RT_OK;
}

/*******************************************************************************
函数原型：	UINT8 ALGRsa_PR_PriKeyOpt_NoCRT(UINT8 *output, UINT32 *outputLen, UINT8 *input, 
									 UINT32 inputLen, R_RSA_PRIVATE_KEY *RSAKey)
函数说明：	私钥操作，此函数没有对数据进行Padding，需要自己Padding。此操作可以对数据进行私钥加密，或者对公钥加密的数据进行解密。私钥中使用了结构体R_RSA_PRIVATE_KEY中的modulus和exponent
参数说明：	output [O] --- 输出结果；
			outputLen [O] --- 输出结果长度，为protoKey->bits/8字节；
			input [I] --- 输入数据；
			inputLen [I] --- 输入数据长度，必须为protoKey->bits/8字节；
			RSAKey [I] --- 私钥，私钥中使用了结构体中的modulus和exponent
返回值：	RT_OK或RT_FAIL
********************************************************************************/
UINT8 ALGRsa_PR_PriKeyOpt_NoCRT(UINT8 *output,UINT32 *outputLen,UINT8 *input,UINT32 inputLen,R_RSA_PRIVATE_KEY *privateKey)
{
	rsa_ctx.len = privateKey->bits/8;
	mbedtls_mpi_read_binary(&rsa_ctx.D, (UINT8*)privateKey->exponent, privateKey->bits/8);
	mbedtls_mpi_read_binary(&rsa_ctx.N, (UINT8*)privateKey->modulus, privateKey->bits/8);
	if(0 != mbedtls_rsa_private_nocrt(&rsa_ctx, NULL, NULL, input, output))
	{
		return RT_FAIL;
	}

	return RT_OK;
}
